package org.youyun56.gpsserver.apache.tomcat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import net.sf.ehcache.search.Result;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.mina.core.session.IoSession;
import org.mortbay.log.Log;
import org.youyun56.gpsserver.CacheFactory;
import org.youyun56.gpsserver.Config;
import org.youyun56.gpsserver.Task;
import org.youyun56.gpsserver.command.Command;
import org.youyun56.gpsserver.command.CommandFactory;
import org.youyun56.gpsserver.common.JSONUtils;
import org.youyun56.gpsserver.common.SessionManager;
import org.youyun56.gpsserver.entity.Good;
import org.youyun56.gpsserver.entity.Im;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

public class GpsHttpHandler implements HttpHandler {
    private final static Logger logger = Logger.getLogger(GpsHttpHandler.class);
    private final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private final static ThreadPoolExecutor pool = new ThreadPoolExecutor(Integer.parseInt(CacheFactory.props
            .getProperty(Config.HttpThread)), Integer.parseInt(CacheFactory.props.getProperty(Config.HttpThread)), 0L,
            TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()) {
        @SuppressWarnings("unchecked")
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            // TODO Auto-generated method stub
            super.afterExecute(r, t);
            Command command = null;
            try {
                command = (Command) ((FutureTask<?>) r).get();
                if (command == Command.AppendGood) {
                    List<Result> rss = (List<Result>) command.getOutput();
                    JSONArray goods = new JSONArray();
                    boolean first = true;
                    long max = -1;
                    if (rss != null) {
                        for (Result rs : rss) {
                            Good good = (Good) rs.getValue();
                            if (first) {
                                max = good.getIndex() == null ? good.getId() : good.getIndex();
                                first = false;
                            }
                            goods.add(CommandFactory.goodJson(good));
                        }
                    }
                    JSONObject o = new JSONObject();
                    o.put("rows", goods);
                    o.put("index", max);
                    HttpResponse response = new HttpResponse(command.getExchange());
                    response.write(o);

                } else if (command == Command.GetGoods) {
                    List<Result> rss = (List<Result>) command.getOutput();
                    JSONArray goods = new JSONArray();
                    boolean first = true;
                    long max = 0;
                    if (rss != null) {
                        for (Result rs : rss) {
                            Good good = (Good) rs.getValue();
                            if (first) {
                                max = good.getIndex() == null ? good.getId() : good.getIndex();
                                first = false;
                            }
                            goods.add(CommandFactory.goodJson(good));
                        }
                    }
                    JSONObject o = new JSONObject();
                    o.put("total", command.getPage().getTotalCount());
                    o.put("rows", goods);
                    o.put("index", max);
                    HttpResponse response = new HttpResponse(command.getExchange());
                    response.write(o);
                } else if (command == Command.AppendGoodEnd) {
                    List<Result> rss = (List<Result>) command.getOutput();
                    JSONArray goods = new JSONArray();
                    if (rss != null) {
                        for (Result rs : rss) {
                            Good good = (Good) rs.getValue();
                            goods.add(CommandFactory.goodJson(good));
                        }
                    }
                    JSONObject o = new JSONObject();
                    o.put("rows", goods);
                    HttpResponse response = new HttpResponse(command.getExchange());
                    response.write(o);
                } else if (command == Command.GoodSearch) {
                    List<Result> rss = (List<Result>) command.getOutput();
                    JSONArray goods = new JSONArray();
                    if (rss != null) {
                        for (Result rs : rss) {
                            Good good = (Good) rs.getValue();
                            goods.add(CommandFactory.goodJson(good));
                        }
                    }
                    JSONObject o = new JSONObject();
                    o.put("rows", goods);
                    HttpResponse response = new HttpResponse(command.getExchange());
                    response.write(o);
                } else if (command == Command.ADDIM) {
                    List<Im> ims = (List<Im>) command.getOutput();
                    for (Im im : ims) {
                        IoSession session = SessionManager.getSession(im.getCityId(), im.getMobile());
                        if (session != null) {
                            session.write(CommandFactory.IMS(im));
                        } else {
                            CacheFactory.instance.addImCache(im.getCityId(), im.getMobile(), im);
                        }
                    }
                    HttpResponse response = new HttpResponse(command.getExchange());
                    response.write(JSONUtils.success());
                } else if (command == Command.AddGood) {
                    Good good = (Good) command.getOutput();
                    HttpResponse response = new HttpResponse(command.getExchange());
                    response.write(JSONUtils.success());
                    SessionManager.brocast(good.getTargetCity(), CommandFactory.sendGood(CommandFactory.goodJson(good))
                            .toString());
                } else {
                    HttpResponse response = new HttpResponse(command.getExchange());
                    response.write(JSONUtils.failure("command not found"));
                }
            } catch (Exception e) {
                logger.error(String.format("input %s occur exception", command.getInput()), e);
            }
        }
    };

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        String query = exchange.getRequestURI().getQuery();
        logger.info(String.format("Command input: %s", query));
        InputStream ips = exchange.getRequestBody();
        BufferedReader br = new BufferedReader(new InputStreamReader(ips));
        String line = null;
        while ((line = br.readLine()) != null) {
            Log.info(line);
        }
        if (StringUtils.isNotEmpty(query)) {
            Task task = Command.getExecute(query);
            if (task != null) {
                task.getCommand().setExchange(exchange);
                pool.submit(task);
            } else {
                HttpResponse response = new HttpResponse(exchange);
                response.write(JSONUtils.failure("no task"));
            }
        }

    }

}
